package com.sak.vis.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.queryParser.QueryParser.Operator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.springframework.stereotype.Service;

import com.sak.vis.domain.Result;

/**
 * Lucene based result optimization service.
 * 
 * @author Saket Vishal
 * 
 */
@Service(value = "luceneResultOptimizationService")
public class LuceneResultOptimizationServiceImpl implements
		ResultOptimizationService {

	private static final int MAX_RESULTS = 5;

	@Override
	public List<Result> optimize(String queryText, List<Result> results) {
		RAMDirectory idx = new RAMDirectory();
		StandardAnalyzer standardAnalyzer = new StandardAnalyzer(
				Version.LUCENE_35);
		IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35,
				standardAnalyzer);

		IndexWriter w;
		try {
			w = new IndexWriter(idx, config);

			int position = 0;
			for (Iterator<Result> iterator = results.iterator(); iterator
					.hasNext();) {
				Result result = (Result) iterator.next();
				addDoc(w, String.valueOf(position),
						result.getTitle() + result.getAddress());

				position++;
			}

			w.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		List<Result> optimizedList = new ArrayList<Result>(3);
		try {
			Query q = new QueryParser(Version.LUCENE_35, "content",
					standardAnalyzer).parse(queryText);

			int hitsPerPage = MAX_RESULTS;
			IndexReader reader = IndexReader.open(idx);
			IndexSearcher searcher = new IndexSearcher(reader);
			TopScoreDocCollector collector = TopScoreDocCollector.create(
					hitsPerPage, true);
			searcher.search(q, collector);
			ScoreDoc[] hits = collector.topDocs().scoreDocs;

			for (int i = 0; i < hits.length; ++i) {
				int docId = hits[i].doc;
				Document d = searcher.doc(docId);
				optimizedList.add(results.get(Integer.valueOf(d.get("index"))));
			}
			searcher.close();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		idx.close();
		return optimizedList;

	}

	private static void addDoc(IndexWriter w, String index, String content)
			throws IOException {
		Document doc = new Document();
		doc.add(new Field("index", index, Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		doc.add(new Field("content", content, Field.Store.YES,
				Field.Index.ANALYZED));

		w.addDocument(doc);
	}

}
